package edu.vsu.amm.chaos.ui;

import edu.vsu.amm.chaos.api.Henon;
import edu.vsu.amm.chaos.api.Parameters;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * User: Илья
 * Date: 10.11.13
 * Time: 16:42
 */
public class GraphicsController {

	@FXML
	private TabPane tabs;

	private List<XYChart<Number, Number>> charts = new ArrayList<>();
	private List<XYChart.Series<Number, Number>> series = new ArrayList<>();

	private double[] initDot;
	private Henon map;
	private int iteration;

	@FXML
	public void initialize() {
		tabs.getTabs().clear();
		makeCharts();
	}

	private void makeCharts() {
		for (int i = 0; i < TITLES.length; i++) {
			AnchorPane anchor = new AnchorPane();
            charts.add(makeChart(anchor, i != 0));
			XYChart.Series<Number, Number> ser = new XYChart.Series<>();
			ser.setName(String.format("Орбита в плоскости %s", TITLES[i]));
			series.add(ser);

			Tab tab = new Tab();
			tab.setText(TITLES[i]);
			tab.setContent(anchor);
			tab.setClosable(false);
			tabs.getTabs().add(tab);
		}
	}

	private XYChart<Number, Number> makeChart(AnchorPane parent, boolean lineChart) {
		XYChart<Number, Number> chart = lineChart ?
            new LineChart<>(new NumberAxis(), new NumberAxis()) :
            new ScatterChart<>(new NumberAxis(), new NumberAxis());
		parent.getChildren().add(chart);
		AnchorPane.setTopAnchor(chart, 0.0);
		AnchorPane.setRightAnchor(chart, 0.0);
		AnchorPane.setBottomAnchor(chart, 0.0);
		AnchorPane.setLeftAnchor(chart, 0.0);

		return chart;
	}

	private void draw(Parameters params) {
		initDot = new double[] { params.getX0(), params.getY0(), 0 };
		map = new Henon(params.getA(), params.getB(), initDot);
		iteration = 0;

		int count = params.getIterations() + 1;
		for (; iteration < count; iteration++) {
			double[] val = next();
			for (int i = 0; i < AXIS.length; i++) {
				series.get(i).getData().add(new XYChart.Data<Number, Number>(val[AXIS[i][0]], val[AXIS[i][1]]));
			}
		}

		int size = charts.size();
		for (int i = 0; i < size; i++) {
			charts.get(i).getData().add(series.get(i));
		}
	}

	private double[] next() {
		return iteration == 0 ? initDot : map.next();
	}

	@FXML
	private void change() {
		stage.close();
		ParametersController.show();
	}

	private static final String[] TITLES = { "xOy", "nOx", "nOy" };

	/*
		x: 0
		y: 1
		n: 2
	 */
	private static final int[][] AXIS = { {0, 1}, {2, 0}, {2, 1} };

	private static Stage stage;

	public static void open(Parameters params) {
		if (params == null) {
			return;
		}

		FXMLLoader loader = new FXMLLoader(GraphicsController.class.getResource("Graphics.fxml"));
		try {
			Parent root = (Parent) loader.load();
			Scene scene = new Scene(root, 760, 560);
			String style = GraphicsController.class.getResource("style.css").toExternalForm();
			scene.getStylesheets().add(style);

			stage = new Stage();
			stage.setScene(scene);
			stage.setTitle("Отображение Хенона - Орбита");
			stage.show();

			GraphicsController controller = loader.<GraphicsController>getController();
			if (controller == null) {
				return;
			}

			controller.draw(params);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
